#include <dirent.h>
#include <iostream>
#include <locale.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


#include "color.h"

using namespace cv;
using namespace std;
/********************************************************************************************
 *函数描述： calcCast 计算并返回一幅图像的色偏度以及，色偏方向
 *函数参数： InputImg 需要计算的图片，BGR存放格式，彩色（3通道），灰度图无效
 * cast 计算出的偏差值，小于1表示比较正常，大于1表示存在色偏
 * da 红/绿色偏估计值，da大于0，表示偏红；da小于0表示偏绿
 * db 黄/蓝色偏估计值，db大于0，表示偏黄；db小于0表示偏蓝
 *函数返回值： 返回值通过cast、da、db三个应用返回，无显式返回值
 *********************************************************************************************/
bool colorException(cv::Mat InputImg) {
  float cast = 1.0, da = 0.0, db = 0.0;
  Mat LABimg;
  cvtColor(
      InputImg, LABimg,
      CV_BGR2Lab); //参考http://blog.csdn.net/laviewpbt/article/details/9335767
  //由于OpenCV定义的格式是uint8，这里输出的LABimg从标准的0～100，-127～127，-127～127，被映射到了0～255，0～255，0～255空间
  float a = 0, b = 0;
  int HistA[256], HistB[256];
  for (int i = 0; i < 256; i++) {
    HistA[i] = 0;
    HistB[i] = 0;
  }
  for (int i = 0; i < LABimg.rows; i++) {
    for (int j = 0; j < LABimg.cols; j++) {
      // a就是所有a分量的总和，b就是所有b分量的总和。
      a += float(LABimg.at<cv::Vec3b>(i, j)[1] -
                 128); //在计算过程中，要考虑将CIE L*a*b*空间还原 后同
      b += float(LABimg.at<cv::Vec3b>(i, j)[2] - 128);
      int x = LABimg.at<cv::Vec3b>(i, j)[1]; //每一个坐标上a分量对应的值。
      int y = LABimg.at<cv::Vec3b>(i, j)[2]; //每一个坐标上b分量对应的值。
      HistA[x]++; //这个是一个256的组数，每一个种颜色的值都会自增1
      HistB[y]++;
    }
  }
  da = a / float(LABimg.rows * LABimg.cols); //所有的a分量占比
  db = b / float(LABimg.rows * LABimg.cols); //所有的b分量占比
  float D = sqrt(da * da + db * db);
  float Ma = 0, Mb = 0;
  for (int i = 0; i < 256; i++) {
    Ma += abs(i - 128 - da) * HistA[i]; //计算范围-128～127
    Mb += abs(i - 128 - db) * HistB[i];
  }
  Ma /= float((LABimg.rows * LABimg.cols));
  Mb /= float((LABimg.rows * LABimg.cols));
  float M = sqrt(Ma * Ma + Mb * Mb);
  float K = D / M;
  cast = K;
  if (cast > 1) {
    cout << "色彩异常！！！色偏值为: " << cast << endl;
    return true;
  }

  // else
  // cout<<"色彩正常，色偏值为: "<<cast<<endl;
  return false;
}